/*
 * Copyright 2022-2025 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.instancio.generator;

import org.instancio.OnCompleteCallback;

/**
 * Specifies actions to be taken on objects generated by a generator.
 * This hint is communicated to the engine via the {@link Generator#hints()} method.
 *
 * <p>Each action determines how the engine processes the generated object,
 * including whether and how its fields are populated or modified.
 *
 * <p>Example usage:
 * <pre>{@code
 * public class CustomGenerator implements Generator<MyObject> {
 *
 *     @Override
 *     public MyObject generate(Random random) {
 *         // Generation logic
 *         return new MyObject();
 *     }
 *
 *     @Override
 *     public Hints hints() {
 *         return Hints.afterGenerate(AfterGenerate.POPULATE_NULLS);
 *     }
 * }
 * }</pre>
 *
 * @see Hints
 * @since 2.0.0
 */
public enum AfterGenerate {

    /**
     * Indicates that a generated object should remain unchanged.
     * The engine will treat the object as read-only and assign it to the target
     * field without further modification.
     *
     * <p>Fields will not be populated, and matching selectors will have no effect.
     * However, {@link OnCompleteCallback} callbacks provided via the {@code onComplete()}
     * method will still be executed.
     *
     * @since 2.0.0
     */
    DO_NOT_MODIFY,

    /**
     * Indicates that a generated object can be modified only via
     * explicitly specified selectors. Fields not targeted by selectors will
     * remain unchanged.
     *
     * @since 2.0.0
     */
    APPLY_SELECTORS,

    /**
     * Indicates that all {@code null} fields in a generated object should be
     * populated by the engine. Additionally, the object can be modified
     * as described by {@link #APPLY_SELECTORS}.
     *
     * <p>Non-null fields will remain unchanged unless explicitly targeted
     * by selectors.
     *
     * @since 2.0.0
     */
    POPULATE_NULLS,

    /**
     * Indicates that both {@code null} fields and primitive fields containing
     * default values in a generated object should be populated by the engine.
     * This includes the behavior of {@link #POPULATE_NULLS}.
     *
     * <p>A primitive field is considered to have a default value if it contains:
     * <ul>
     *   <li>{@code 0} for numeric types ({@code byte}, {@code short}, {@code int},
     *       {@code long}, {@code float}, {@code double})</li>
     *   <li>{@code false} for {@code boolean}</li>
     *   <li>{@code '\u0000'} (null character) for {@code char}</li>
     * </ul>
     *
     * <p>For example:
     * <ul>
     *   <li>A {@code boolean} field with the value {@code false} may be randomized.</li>
     *   <li>A {@code boolean} field with the value {@code true} will remain unchanged.</li>
     *   <li>An {@code int} field with the value {@code 0} may be randomized.</li>
     *   <li>An {@code int} field with a non-zero value will remain unchanged.</li>
     * </ul>
     *
     * @since 2.0.0
     */
    POPULATE_NULLS_AND_DEFAULT_PRIMITIVES,

    /**
     * Indicates that all fields in a generated object should be populated,
     * regardless of their current values. This will overwrite all fields with
     * new random values.
     *
     * <p>This is the default behaviour for internal generators.
     *
     * @since 2.0.0
     */
    POPULATE_ALL
}
